# encoding: utf-8
"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by lane.chang on '17/10/2024'
    comment: agent配置
"""
from fastapi import APIRouter, Request, Body, Query, responses

from config import Config
from project.core.function import json_response
from project.lib.common import Global
from project.lib.decorator import api_common, exec_duration
from project.lib.constant import DEFAULT_VALUE
from project.model.database.agent import Agent, Chat, ChatMessage
from project.model.database.knowledge import Knowledge
from project.service.agent import AgentService
from project.micro_service.zeus import Zeus
from project.model.basic import FlushDeviceMode


agent_router = APIRouter(prefix='/m', tags=['manager.agent'])


@agent_router.post('/agent/add', summary='新增agent')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_agent_add(request: Request,
                       title: str = Body(..., max_length=30, title='标题'),
                       image: str = Body('', max_length=200, title='知识库图片'),
                       session=None,
                       body_params=None,
                       operator=None):
    """
    **desc**: 新增agent

    **url**: http(s)://{0}.udicaria.com/m/agent/add

    **method**: POST

    **params**:

        <body>:
            title: 标题
            image: 图片

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    agent = await AgentService.add_agent(session, operator, body_params)

    return json_response(data=agent.dict('id', 'code'))


@agent_router.post('/agent/update', summary='修改agent')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_agent_update(request: Request,
                          id: int = Body(..., title='智能体id'),
                          title: str = Body(DEFAULT_VALUE, max_length=30, title='标题'),
                          image: str = Body(DEFAULT_VALUE, max_length=200, title='知识库图片'),
                          prologue: str = Body(DEFAULT_VALUE, max_length=200, title='开场白'),
                          ai_config: str = Body(DEFAULT_VALUE, max_length=200, title='AI配置'),
                          knowledge_ids: list[int] = Body(DEFAULT_VALUE, title='关联的知识库id列表'),
                          session=None,
                          body_params=None):
    """
    **desc**: 修改agent

    **url**: http(s)://{0}.udicaria.com/m/agent/update

    **method**: POST

    **params**:

        <body>:
            id: 智能体id
            title: 标题
            image: 知识库图片
            prologue: 开场白
            ai_config: AI配置
            knowledge_ids: 关联的知识库id列表

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.update_agent(session, body_params)

    return json_response()


@agent_router.get('/agent/detail', summary='agent详情')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_agent_detail(request: Request, id: int = Query(..., title='智能体id'), session=None):
    """
    **desc**: agent详情

    **url**: http(s)://{0}.udicaria.com/m/agent/detail

    **method**: GET

    **params**:

        <query>:
            id: 智能体id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                code: 智能体编号
                title: 智能体标题
                image: 智能体图片
                prologue: 开场白
                ai_config: AI配置
                operator_code: 所有者编号
                operator_name: 所有者名称
                knowledge_ids: 关联知识库id列表
                knowledges: [
                    {
                        id: 知识库id
                        title: 知识库标题
                        image: 图片
                    }
                ] 知识库列表
                bind_knowledge_count: 关联知识库数量
            }
            exec_time: 接口后端处理时长
        }
    """
    agent = await Agent.fetch_one(session, wheres=(Agent.id == id))
    if not agent:
        return json_response(data={})

    ret_data = agent.dict()
    operators = await Zeus.get_operator_list(codes=[agent.operator_code])
    operator_map = {v['code']: v['name'] for v in operators}
    ret_data['operator_name'] = operator_map.get(agent.operator_code, '')

    knowledges = await Knowledge.fetch_all(session, wheres=(Knowledge.id.in_(agent.knowledge_ids), ~Knowledge.is_deleted))
    ret_data['knowledges'] = [v.dict('id', 'title', 'image') for v in knowledges]

    return json_response(data=ret_data)


@agent_router.get('/agent/list', summary='agent列表')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_agent_list(request: Request, session=None, operator=None):
    """
    **desc**: agent列表

    **url**: http(s)://{0}.udicaria.com/m/agent/list

    **method**: GET

    **params**:

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                code: 智能体编号
                title: 智能体标题
                image: 智能体图片
                operator_code: 所有者编号
                operator_name: 所有者名称
                bind_knowledge_count: 关联知识库数量
                is_default: 是否默认
            }
            exec_time: 接口后端处理时长
        }
    """
    data = await Agent.fetch_all(session, wheres=(Agent.organization_code == operator.organization_code, ~Agent.is_deleted))
    if not data:
        return json_response(data=[])

    # 取得所有信息
    operator_codes = [v.operator_code for v in data]
    operators = await Zeus.get_operator_list(codes=operator_codes)
    operator_map = {v['code']: v['name'] for v in operators}

    items = []
    for v in data:
        d = v.dict()

        d['operator_name'] = operator_map.get(v.operator_code, '')
        items.append(d)

    return json_response(data=items)


@agent_router.post('/agent/delete', summary='删除agent')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_agent_delete(request: Request, id: int = Body(..., title='智能体id', embed=True), session=None):
    """
    **desc**: 删除智能体

    **url**: http(s)://{0}.udicaria.com/m/agent/delete

    **method**: POST

    **params**:

        <body>:
            id: 智能体id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.delete_agent(session, agent_id=id)

    return json_response()


@agent_router.post('/agent/set/default', summary='设置默认')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_agent_set_default(request: Request,
                               id: int = Body(..., title='智能体id'),
                               flush_device_mode: FlushDeviceMode.enums(fixed=Global.count(), with_blank='') = Body('nothing', title='刷新设备类型'),
                               session=None):
    """
    **desc**: 设置默认机构智能体

    **url**: http(s)://{0}.udicaria.com/m/agent/set/default

    **method**: POST

    **params**:

        <body>:
            id: 智能体id
            flush_device_mode:
                default_device_only: 只更新旧默认智能体的设备
                whole_organization: 更新机构下所有设备
                nothing: 不做任何事情


    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.set_default_agent(session, id, flush_device_mode)

    return json_response()


@agent_router.post('/agent/conversation/create', summary='新建会话')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def create_conversation(request: Request,
                              id: int = Body(..., title='智能体id', embed=True),
                              session=None):
    """
    **desc**: 新建会话

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/create

    **method**: POST

    **params**:

        <body>:
            id: 智能体id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                conversation_id: 会话id
            }
            exec_time: 接口后端处理时长
        }
    """
    conversation_id = await AgentService.create_conversation(session, agent_id=id)

    return json_response(data={'conversation_id': conversation_id})


@agent_router.post('/agent/chat/streaming', summary='智能体对话')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_agent_chat(request: Request,
                        conversation_id: str = Body(..., title='会话id'),
                        user_message: str = Body(..., title='用户话术'),
                        session=None):
    """
    **desc**: 智能体对话(流式)

    **url**: http(s)://{0}.udicaria.com/m/agent/chat/streaming

    **method**: POST

    **params**:

        <body>:
            conversation_id: 会话id
            user_message: 用户话术

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                response: 智能体话术
            }
            exec_time: 接口后端处理时长
        }
    """
    ret_data = await AgentService.do_agent_chat_streaming(session, conversation_id, user_message)

    return responses.StreamingResponse(ret_data, media_type='text/plain')


@agent_router.post('/agent/conversation/save', summary='保存会话')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def save_conversation(request: Request,
                            conversation_id: str = Body(..., title='会话id', embed=True),
                            session=None):
    """
    **desc**: 保存会话

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/save

    **method**: POST

    **params**:

        <body>:
            conversation_id: 会话id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.save_conversation(session, conversation_id)

    return json_response()


@agent_router.post('/agent/conversation/update', summary='修改会话')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def update_conversation(request: Request,
                              conversation_id: str = Body(..., title='会话id'),
                              title: str = Body(DEFAULT_VALUE, max_length=30, title='会话标题'),
                              remark: str = Body(DEFAULT_VALUE, max_length=200, title='备注信息'),
                              session=None,
                              body_params=None):
    """
    **desc**: 保存会话

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/update

    **method**: POST

    **params**:

        <body>:
            conversation_id: 会话id
            title: 会话标题
            remark: 备注信息

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.update_conversation(session, conversation_id, body_params)

    return json_response()


@agent_router.get('/agent/conversation/detail', summary='会话详情')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_conversation_detail(request: Request, conversation_id: str = Query(..., title='会话id'), session=None):
    """
    **desc**: 会话详情

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/detail

    **method**: GET

    **params**:

        <body>:
            conversation_id: 会话id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                id: 对话日志id
                conversation_id: 会话id
                agent_id: 智能体id
                title: 标题
                message_count: 消息总数
                remark: 备注信息
                create_time: 时间
                messages: [
                    {
                        role: user(用户)/agent(智能体)
                        message: 话术文本
                    }
                ] 会话消息列表
            }
            exec_time: 接口后端处理时长
        }
    """
    chat = await Chat.fetch_one(session, wheres=(Chat.conversation_id == conversation_id))
    if not chat:
        return json_response(data={})
    ret_data = chat.dict()

    data = await ChatMessage.fetch_all(session, wheres=(ChatMessage.chat_id == chat.id, ~ChatMessage.is_deleted), orders=(ChatMessage.id,))
    ret_data['messages'] = [v.dict() for v in data]

    return json_response(data=ret_data)


@agent_router.get('/agent/conversation/list', summary='会话列表')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_agent_chat_list(request: Request,
                              id: int = Query(..., title='智能体id'),
                              session=None):
    """
    **desc**: 对话日志列表

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/list

    **method**: GET

    **params**:

        <query>:
            id: 智能体id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                id: 对话日志id
                conversation_id: 会话id
                agent_id: 智能体id
                title: 标题
                message_count: 消息总数
                remark: 备注信息
                create_time: 时间
            }
            exec_time: 接口后端处理时长
        }
    """
    data = await Chat.fetch_all(session, wheres=(Chat.agent_id == id, ~Chat.is_deleted), orders=(Chat.id.desc()))
    items = [v.dict() for v in data]

    return json_response(data=items)


@agent_router.post('/agent/conversation/delete', summary='删除会话')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def delete_conversation(request: Request,
                              conversation_id: str = Body(..., title='会话id', embed=True),
                              session=None):
    """
    **desc**: 删除会话

    **url**: http(s)://{0}.udicaria.com/m/agent/conversation/delete

    **method**: POST

    **params**:

        <body>:
            conversation_id: 会话id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await AgentService.delete_conversation(session, conversation_id)

    return json_response()
